#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow){
    ui->setupUi(this);
        //QObject::connect(&mystack,SIGNAL(StackAdaptor::stackChanged()),this,SLOT(update()));
        print = 5;

        QObject::connect(ui->spinBox,SIGNAL(valueChanged(int)),this,SLOT(setPrint(int)));

        QObject::connect(ui->num0Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num1Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num2Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num3Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num4Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num5Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num6Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num7Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num8Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->num9Button,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->iButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->spaceButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->PointButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->quoteButton,SIGNAL(clicked()),this,SLOT(editLine()));

        QObject::connect(ui->plusButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->minusButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->multiplyButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->divisionButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorCOSButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorSINButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorTANButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorEVALButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorSQRTButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorPOWbutton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorMODButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorFRACButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorSQRButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorINVButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorLOGButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorLNButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorSIGNButton,SIGNAL(clicked()),this,SLOT(editLine()));
        QObject::connect(ui->operatorCUBEButton,SIGNAL(clicked()),this,SLOT(editLine()));

        QObject::connect(ui->swapButton,SIGNAL(clicked()),this,SLOT(stackSwap()));
        QObject::connect(ui->sumButton,SIGNAL(clicked()),this,SLOT(stackSum()));
        QObject::connect(ui->meanButton,SIGNAL(clicked()),this,SLOT(stackMean()));
        QObject::connect(ui->dupButton,SIGNAL(clicked()),this,SLOT(stackDup()));
        QObject::connect(ui->dropButton,SIGNAL(clicked()),this,SLOT(stackDrop()));

        QObject::connect(ui->enterButton,SIGNAL(clicked()),this,SLOT(operate()));
        QObject::connect(ui->delButton,SIGNAL(clicked()),this,SLOT(remove()));
        QObject::connect(ui->clearButton,SIGNAL(clicked()),this,SLOT(clear()));
        QObject::connect(ui->actionKeyboard,SIGNAL(toggled(bool)),this,SLOT(showdetails(bool)));

        QObject::connect(ui->actionRevert,SIGNAL(triggered()),this,SLOT(undo()));
        QObject::connect(ui->actionRedo,SIGNAL(triggered()),this,SLOT(redo()));

        for(int j=0;j<history.size();j++){
                std::string tmp = history[j].toStdString();
                std::vector<string> v = Calculateur::parser(tmp);

                for(int i=0;i<v.size();i++)
                       ConstanteFactory::ConstantesFactory(v[i],mystack);
                update();

        }
}


void MainWindow::editLine(){
        QPushButton& tmp = static_cast<QPushButton&>(*QObject::sender());
        QString tmp1;
        if(tmp.text() == "_")
            tmp1 = " ";
        else if ((tmp.text() == "SIN" ||tmp.text() == "COS" || tmp.text() == "TAN") && ui->HcheckBox->isChecked())
            tmp1 = tmp.text() + "H";
        else
            tmp1 = tmp.text();

        ui->lineEdit_3->setText(ui->lineEdit_3->text()+tmp1);
        update();
 }

void MainWindow::remove(){
        QString tmp = ui->lineEdit_3->text();
        tmp.truncate(ui->lineEdit_3->text().size()-1);
        ui->lineEdit_3->setText(tmp);
 }

void MainWindow::redo(){
           std::vector<string> v = Calculateur::parser(history.current().toStdString());
        if(history.next())
           for(int i=0;i<v.size();i++)
                ConstanteFactory::ConstantesFactory(v[i],mystack);
            ui->lineEdit_3->setText(history.current());
            update();
 }

void MainWindow::undo(){
        if(history.previous()){
        ui->lineEdit_3->setText(history.current());
        mystack.drop();
        update();
        }
 }

void MainWindow::clear(){
        ui->lineEdit_3->setText("");
        this->mystack.clear();
        this->history.clear();
        ui->textEdit->setText("");
 }

void MainWindow::showdetails(bool b){
        this->ui->UnaryOperatorKeyboardWidget->setVisible(b);
        this->ui->BinaryOperatorKeyboardFrame->setVisible(b);
        this->ui->MainKeyboardWidget->setVisible(b);
 }

void MainWindow::operate(){
        std::vector<string> v = Calculateur::parser(ui->lineEdit_3->text().toStdString());
        history.add(ui->lineEdit_3->text());

        try{
               for(int i=0;i<v.size();i++)
                      ConstanteFactory::ConstantesFactory(v[i],mystack);
        }
        catch(std::exception const& e)
           {
               ui->label->setText(QString("ERREUR : ")+ e.what());
                history.clear();
           }
        ui->lineEdit_3->setText("");
        update();
 }

MainWindow::~MainWindow()
{
        history.save();
    delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void MainWindow::stackSwap(){
        Constante *x,*y;
        x = mystack.top();
        mystack.drop();
        y = mystack.top();
        mystack.drop();
        mystack.swap(static_cast<Integer*>(x)->getVal()-1,static_cast<Integer*>(y)->getVal()-1);
        update();

}
void MainWindow::stackSum(){
        mystack.sum();
        update();
}
void MainWindow::stackMean(){
        mystack.mean();
        update();
}
void MainWindow::stackDup(){
        Integer x(0);
        mystack.add(Addition::apply(x,*mystack.top()));
        update();
}
void MainWindow::stackDrop(){
        mystack.drop();
        update();
}

    void MainWindow::update(){
        ui->textEdit->setText(QString(mystack.print(print).c_str()));
    }

void MainWindow::setPrint(int n){
        print = n;
        update();
}
